package com.cardone.generator.dictionary;

import com.cardone.common.util.MapperUtils;
import com.cardone.context.ContextHolder;
import com.cardone.context.action.Run0Action;
import com.cardone.context.action.Run1Action;
import com.cardone.context.function.Execution1Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.support.TaskUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created by c100000002 on 15-1-12.
 */
@Slf4j
public class Generator implements Run0Action {
    @Override
    public void run() {
        if (!validatorConfig()) {
            log.error("未配置完整");

            return;
        }

        TaskExecutor taskExecutor = ContextHolder.getBean(TaskExecutor.class);

        Runnable runnable = () -> {
            try {
                Thread.sleep(9000);
            } catch (InterruptedException e) {
                log.error(e.getMessage(), e);
            }

            Map<String, List<Map<String, Object>>> dictionaryListMap = findListByTypeCodesFunction.execution(this.typeCodes);

            if (MapUtils.isEmpty(dictionaryListMap)) {
                return;
            }

            this.save(dictionaryListMap);
        };


        if (taskExecutor == null) {
            new Thread(() -> runnable.run()).run();

            return;
        }

        taskExecutor.execute(TaskUtils.decorateTaskWithErrorHandler(runnable, null, true));
    }

    private void save(Map<String, List<Map<String, Object>>> dictionaryListMap) {
        Map<String, List<Map<String, Object>>> newDictionaryListMap = Maps.newHashMap();

        for (Map.Entry<String, List<Map<String, Object>>> dictionaryListMapEntry : dictionaryListMap.entrySet()) {
            List<Map<String, Object>> newDictionaryList = Lists.newArrayList();

            for (Map<String, Object> dictionary : dictionaryListMapEntry.getValue()) {
                Map<String, Object> newDictionary = Maps.newHashMap();

                for (Map.Entry<String, String> dictionaryMapEntry : dictionaryMap.entrySet()) {
                    newDictionary.put(dictionaryMapEntry.getKey(), dictionary.get(dictionaryMapEntry.getValue()));
                }

                newDictionaryList.add(newDictionary);
            }

            newDictionaryListMap.put(dictionaryListMapEntry.getKey(), newDictionaryList);
        }

        String jsStr = "var " + varName + " = ";

        jsStr += MapperUtils.toJson(newDictionaryListMap) + ";";

        try {
            if (saveLocation.getFile().exists()) {
                saveLocation.getFile().delete();
            }

            FileUtils.writeStringToFile(saveLocation.getFile(), jsStr);

            if (savedAction != null) {
                savedAction.run(saveLocation.getFile());
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Setter
    private String varName = "dict";

    /**
     * 验证配置是否完整
     *
     * @return
     */
    private boolean validatorConfig() {
        if (findListByTypeCodesFunction == null) {
            return false;
        }

        if (saveLocation == null) {
            return false;
        }

        if (StringUtils.isBlank(typeCodes)) {
            return false;
        }

        if (MapUtils.isEmpty(dictionaryMap)) {
            return false;
        }

        return true;
    }

    @Setter
    private Map<String, String> dictionaryMap;

    /**
     * 文件位置
     */
    @Setter
    private Resource saveLocation;

    @Setter
    private Run1Action<File> savedAction;

    @Setter
    private Execution1Function<Map<String, List<Map<String, Object>>>, String> findListByTypeCodesFunction;

    @Setter
    private String typeCodes = "sex,test";
}
